﻿//
// Created by LiuYou on 2021/4/9.
//

/**
 * @brief 动态内存分配函数
 * dynamic memory allocation
 * C语言的动态内存分配函数从堆上分配内存。使用这些函数需要包含头文件 <stdlib.h>
 * 1. malloc()
 *      void* malloc(unsigned int size);
 *      用来分配若干字节的内存空间，返回一个指向该分配的内存首地址的指针。如果不能分配这么大的内存空间或者分配失败，malloc()函数返回空指针NULL。
 *      size: 向系统申请空间的大小(size个字节)，函数调用成功后返回一个指向void类型的指针。
 *      void* 指针是一种指针类型，具有一般性，通常称为通用指针(generic pointer)或者无类型指针(typeless pointer)。
 *      所以调用该函数后，函数的返回值赋予某个指针时，需要对返回值进行类型强转成想赋值的指针的类型。
 *      例:
 *          int* ptrInteger = (int*)malloc(4);
 *      如果不知道不能确定某种类型所占内存的字节数时，可以使用sizeof关键字计算类型所占的字节数。
 *      例:
 *          int* ptrInteger = (int*)malloc(sizeof(int));
 *          而且这种方法有利于提高程序的可移植性。
 *
 * 2. calloc()
 *      void* calloc(unsigned int num, unsigned int size);
 *      动态定义一个一维数组或者二维数组。
 *      num: 向系统申请的内存空间的数量，一位数组的长度/或者是 m*n m行n列的二维数组。
 *      size: 申请每个空间的字节数，数组元素的类型所占的内存字节
 *      函数返回值是数组的首地址，但是也是void* 类型。所以需要进行强转成所需要的指针类型。
 *      例:
 *          double* ptrDouble = (double*)calloc(10, sizeof(double));
 *          相当于
 *          double* ptrDouble = (double*)malloc(10*sizeof(double));
 *      但是与malloc()不同的是: calloc()能自动将分配的内存初始化为0，而malloc()不能。
 *      但是可以使用memset()进行清零操作。
 *
 * 3. free()
 *      void* free(void* p);
 *      释放向系统动态申请的由指针p指向的存储空间。
 *      p: p的地址只能是由malloc()和callc()申请内存时返回的地址。
 *
 * 4. realloc()
 *      void* realloc(void* p, unsigned int size);
 *      用来改变原来分配的存储空间的大小。
 *      将指针p所指向的存储空间的大小改为size个字节，函数的返回值是新分配的存储空间的首地址，与原来分配的首地址不一定相同。
 *      我觉得这个函数一般不使用！
 *
 * memory leak(内存泄漏)
 * 野指针: 释放了内存但是仍然在之后的程序中使用到了这个指针。野指针不是空指针。
 */
void dynamicMemoryAllocateFunction() {


}

//int main(int argc, char* argv[]) {
int main(int argc, char** argv) {
    /*
     C程序的内存:
        * 内存高端
        * 动态存储区
             栈
             堆
        * 静态存储区
             全局变量
             静态变量
        * 只读存储区
             字符串常量
             程序的机器代码
        * 内存低端
     */
    /*
     C语言中变量的内存分配有以下3种:
        * 从静态存储区分配
            程序的全局变量和静态变量都是在静态存储区分配，而且
            是在程序编译时已经分配好，在程序运行期间一直占用这块内存，仅在程序终止前才被操作系统回收。
        * 从栈上分配
            在执行函数调用(invoke function/method)时，系统在栈上为函数的局部变量和函数中的形参分配内存，
            函数执行结束时，自动释放这些内存。
        * 从堆上分配
            在程序运行期间，用动态内存分配函数来申请的内存都是从堆上分配的。动态内存的生存期(生命期)由程序员来
            决定，非常灵活，但是也最容易出现内存泄漏问题。
     */

    return 0;
}